package com.qf.juc.demo.inject;

public class Demo2 {

    public static void main(String[] args) {
        // StringTable串池 ["a","b","ab"]
        String s1 = "a";
        // 常量池中的字符串仅是符号，第一次用到时才变为对象 ,没用到的时候就在常量池中，第一用到时才变为对象，
        // 如果此时串池（StringTable）中没有"a",就直接存放在串池中,如果串池中有"a",就返回"a"的对象给s1,利用串池的机制，来避免重复创建字符串对象
        String s2 = "b";

        // 字符串常量拼接，字符串常量拼接的原理是编译期优化 ，如果串池中有"ab"，就直接将引用指向该"ab",如果没有就将"ab"对象放入串池中
        String s3 = "a" + "b";
        // 字符串变量拼接的原理是 StringBuilder （1.8）,底层调用StringBuilder,
        // 分别将s1(a)和s2(b)拼接到一起，并创建一个新的String对象 ,在堆中存放，并没有放到串池中
        String s4 = s1 + s2;
        // 此时串池中已经有了"ab",所以就直接将"ab"(s3)的对象返回给了s5,所以s3和s5的地址是相等的
        String s5 = "ab";
        // 此时s4对象调用intern()试图将s4对象放入串池，由于串池中已经有了"ab"对象,所以没能将s4对象放入串池中，s4此时还是存放在堆中，
        // 而是将串池中的"ab"(s3)对象返回给了s6,所以s3的地址和s6的地址相同。
        String s6 = s4.intern();


        // 问
        System.out.println(s3 == s4); // false
        System.out.println(s3 == s5); // true
        System.out.println(s3 == s6); // true

        // StringTable串池 ["a","b","ab","c","d","cd"]
        // 此写法是先将字符串常量"c","d"放入常量池中，再new对象，最后通过StringBuilder来将字符串拼接，最后创建String("cd"),其对象放在堆内存中
//		String x2 = new String("c") + new String("d");
        // 由于此时串池中没有"cd",就直接将"cd"(x1)存放到串池中，
//		String x1 = "cd";
        // x2对象调用intern()来将x2存放到串池中，但是此时串池中已经有了"cd"，故没有将X2对象存入串池中，此时X2对象存放在堆中,所以X1和X2的地址不相等。
//		x2.intern();

//		 System.out.println(x1 == x2); // false

        // 问，如果调换了【最后两行代码】的位置呢，如果是jdk1.6呢 System.out.println(x1 == x2);
        // StringTable串池 ["a","b","ab","c","d","cd"(X2)]
        // 此写法是先将字符串常量"c","d"放入常量池中，再new对象，最后通过StringBuilder来将字符串拼接，最后创建String("cd"),其对象放在堆内存中
        String x2 = new String("c") + new String("d");
        // X2调用intern方法试图将X2对象放入串池中，由于串池中没有"cd"，故直接将X2("cd")存入串池中，X2的地址现在串池中
        x2.intern();
        // 此时串池中已经"cd"（X2)，因此没有将这个"cd"存入串池中，而是将X2("cd")的对象返回给了X1，所以X1的地址就和X2的地址相等
        String x1 = "cd";
        System.out.println(x1 == x2); // true,如果是JDK1.6，此时就是false，因为，X2在调用intern()时，串池中没有"cd"，就将X2的对象复制一份存入到串池中
        // 此时串池中的存的是X2复制的新对象,String x1 = "cd";执行这行代码时，由于串池中存着X2复制的新对象"cd",所以将这个新对象的地址返回给了X1，所以最终X1和X2的地址不相等。
        //可以使用 intern 方法，主动将串池中还没有的字符串对象放入串池
        //1.8 将这个字符串对象尝试放入串池，如果有则并不会放入，如果没有则放入串池， 会把串 池中的对象返回
        //1.6 将这个字符串对象尝试放入串池，如果有则并不会放入，如果没有会把此对象复制一份， 放入串池， 会把串池中的对象返回

    }

}
